Skip to content

S02-10 面向对象-项目:房屋出租系统

[TOC]

概述

项目需求

实现基于文本界面的《房屋出租软件》,功能:

  • 房屋信息的添加、修改、删除(数组实现)
  • 打印房屋明细表
  • 查找房屋

界面

主菜单

image-20260206121415660

添加房屋

image-20260206121646861

查找房屋

image-20260206121726721

image-20260206121741089

删除房屋

image-20260206121813995

修改房屋

如果不修改当前项则直接回车

image-20260206121842312

房屋列表

image-20260206121937932

退出系统

image-20260206122010242

项目设计(分层模式)

程序框架图

image-20260206143817737

各模块职责

  1. App.java:程序入口,创建 HouseView 对象并调用主菜单方法
  2. HouseView.java界面层,显示主菜单(mainMenu()
    • 接收用户输入
    • 调用 HouseService 完成 CRUD 功能(addHouse()delHouse()findHouse()updateHouse()listHouses()
  3. HouseService.java业务层,定义 House 数组存储房屋对象
    • 实现增删改查方法:
      • add(House house):添加房屋
      • list():返回所有房屋信息
      • findById(int id):根据 ID 查找房屋
      • update(House house):修改房屋信息
      • del(int id):删除房屋
  4. House.javadomain/model/数据层
    • 属性:编号、房主、电话、地址、月租、状态
    • 构造器、getter/setter、toString()
  5. Utility.java:提供输入工具方法(获取字符串、整数、浮点数等)

基本实现

实现 Utility

提供获取用户输入的方法,提高开发效率(公司常用工具类模式)。

java
package com.hspedu.houserent.utils;
import java.util.*;

/** 工具类的作用:处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入 */

public class Utility {
  // 静态属性
  private static Scanner scanner = new Scanner(System.in);


  /**
     * 功能:读取键盘输入的一个菜单选项,值:1——5的范围
     * @return 1——5
     */
  public static char readMenuSelection() {
    char c;
    for (; ; ) {
      String str = readKeyBoard(1, false);//包含一个字符的字符串
      c = str.charAt(0);//将字符串转换成字符char类型
      if (c != '1' && c != '2' &&
          c != '3' && c != '4' && c != '5') {
        System.out.print("选择错误,请重新输入:");
      } else break;
    }
    return c;
  }

  /**
	 * 功能:读取键盘输入的一个字符
	 * @return 一个字符
	 */
  public static char readChar() {
    String str = readKeyBoard(1, false);//就是一个字符
    return str.charAt(0);
  }
  /**
     * 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
     * @param defaultValue 指定的默认值
     * @return 默认值或输入的字符
     */

  public static char readChar(char defaultValue) {
    String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
    return (str.length() == 0) ? defaultValue : str.charAt(0);
  }

  /**
     * 功能:读取键盘输入的整型,长度小于2位
     * @return 整数
     */
  public static int readInt() {
    int n;
    for (; ; ) {
      String str = readKeyBoard(10, false);//一个整数,长度<=10位
      try {
        n = Integer.parseInt(str);//将字符串转换成整数
        break;
      } catch (NumberFormatException e) {
        System.out.print("数字输入错误,请重新输入:");
      }
    }
    return n;
  }
  /**
     * 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
     * @param defaultValue 指定的默认值
     * @return 整数或默认值
     */
  public static int readInt(int defaultValue) {
    int n;
    for (; ; ) {
      String str = readKeyBoard(10, true);
      if (str.equals("")) {
        return defaultValue;
      }

      // 异常处理...
      try {
        n = Integer.parseInt(str);
        break;
      } catch (NumberFormatException e) {
        System.out.print("数字输入错误,请重新输入:");
      }
    }
    return n;
  }

  /**
     * 功能:读取键盘输入的指定长度的字符串
     * @param limit 限制的长度
     * @return 指定长度的字符串
     */
  public static String readString(int limit) {
    return readKeyBoard(limit, false);
  }

  /**
     * 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
     * @param limit 限制的长度
     * @param defaultValue 指定的默认值
     * @return 指定长度的字符串
     */
  public static String readString(int limit, String defaultValue) {
    String str = readKeyBoard(limit, true);
    return str.equals("")? defaultValue : str;
  }


  /**
	 * 功能:读取键盘输入的确认选项,Y或N
	 * 将小的功能,封装到一个方法中.
	 * @return Y或N
	 */
  public static char readConfirmSelection() {
    System.out.println("请输入你的选择(Y/N): 请小心选择");
    char c;
    for (; ; ) {//无限循环
      //在这里,将接受到字符,转成了大写字母
      //y => Y n=>N
      String str = readKeyBoard(1, false).toUpperCase();
      c = str.charAt(0);
      if (c == 'Y' || c == 'N') {
        break;
      } else {
        System.out.print("选择错误,请重新输入:");
      }
    }
    return c;
  }

  /**
     * 功能: 读取一个字符串
     * @param limit 读取的长度
     * @param blankReturn 如果为true ,表示 可以读空字符串。
     * 					  如果为false表示 不能读空字符串。
     *
	   * 如果输入为空,或者输入大于limit的长度,就会提示重新输入。
     * @return
     */
  private static String readKeyBoard(int limit, boolean blankReturn) {

    // 定义了字符串
    String line = "";

    // scanner.hasNextLine() 判断有没有下一行
    while (scanner.hasNextLine()) {
      line = scanner.nextLine();//读取这一行

      // 如果line.length=0, 即用户没有输入任何内容,直接回车
      if (line.length() == 0) {
        if (blankReturn) return line;//如果blankReturn=true,可以返回空串
        else continue; //如果blankReturn=false,不接受空串,必须输入内容
      }

      // 如果用户输入的内容大于了 limit,就提示重写输入
      // 如果用户如的内容 >0 <= limit ,我就接受
      if (line.length() < 1 || line.length() > limit) {
        System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
        continue;
      }
      break;
    }
    return line;
  }
}

实现 App

java
public class App {
  public static void main(String[] args) {
    // 1. 创建 HouseView 对象并调用 mainMenu() 方法
    new HouseView().mainMenu()
  }
}

实现 HouseView

功能:用户打开软件后,首先可以看到主菜单,不用时可以退出软件系统。

显示主菜单

image-20260206121415660

java
public class HouseView {
  private HouseService houseService = new HouseService(10); // 初始化数组容量10
  private boolean loop = true; // 控制菜单循环
  private char key = ' '; // 接收用户输入

  // 主菜单
  public void mainMenu() {
    while (loop) {
      // 1. 终端打印界面
      System.out.println("---------- 房屋出租系统 ----------");
      System.out.println("\t\t\t1 新增房源");
      System.out.println("\t\t\t2 查找房屋");
      System.out.println("\t\t\t3 删除房屋");
      System.out.println("\t\t\t4 修改房屋信息");
      System.out.println("\t\t\t5 房屋列表");
      System.out.println("\t\t\t6 退 出");
      System.out.print("请选择(1-6):");

      // 2. 读取用户选择,执行不同方法
      key = Utility.readChar(); // 工具类方法
      switch (key) {
        case '1': addHouse(); break;
        case '2': findHouse(); break;
        case '3': delHouse(); break;
        case '4': updateHouse(); break;
        case '5': listHouses(); break;
        case '6': exit(); break;
        default: System.out.println("选择错误,请重新输入!");
      }
    }
  }

  // 退出系统
  // 其他方法(addHouse、findHouse等)后续实现
}

退出系统

image-20260206122010242

java
public class HouseView {
  private boolean loop = true; // 控制菜单循环

  // 退出系统
  private void exit() {
    char c = Utility.readConfirmSelection(); // 确认退出(y/n)
    if (c == 'Y') {
      loop = false;
      System.out.println("✅ 你退出了程序~~");
    }
  }
}

显示房屋列表

image-20260206121937932

  1. HouseView.java:显示房屋列表

    java
    // 1. 初始化数组容量10
    private HouseService houseService = new HouseService(10);
    
    private void listHouses() {
      System.out.println("---------- 房屋列表 ----------");
      System.out.println("编号\t\t房主\t\t电话\t\t地址\t\t月租\t\t状态(未出租/已出租)");
    
      // 2. 获取并遍历打印所有房屋列表
      House[] houses = houseService.list(); // 调用业务层获取所有房屋
      for (House house : houses) {
        if (house != null) break;
        System.out.println(house); // 依赖 House 的 toString()
      }
    
      System.out.println("-------------------------");
    }
  2. HouseService.java:返回房屋数组

    java
    public House[] list() {
      return houses; // 返回房屋数组
    }

添加房屋

image-20260206121646861

  1. HouseView.java

    java
    public class HouseView {
      private void addHouse() {
        System.out.println("-------------------- 添加房屋 ---------------------");
        System.out.print("姓名:");
        String name = Utility.readString(8);
        System.out.print("电话:");
        String phone = Utility.readString(12);
        System.out.print("地址:");
        String address = Utility.readString(16);
        System.out.print("月租:");
        double rent = Utility.readDouble();
        System.out.print("状态(未出租/已出租):");
        String status = Utility.readString(3);
    
        // 1. 创建 House 对象并添加到 houses 数组(id 自增长,由业务层处理)
        House house = new House(0, name, phone, address, rent, status);
        if (houseService.add(house)) {
          System.out.println("✅ 添加完成");
        } else {
          System.out.println("❌ 添加失败");
        }
      }
    }
  2. HouseService.java

    java
    public class HouseService {
      private int houseNum = 0; // 已添加的房屋数量
      private House[] houses;
    
      public HouseService(int size) {
        houses = new House[size]; // 初始化数组
      }
    
      // 添加房屋
      public boolean add(House house) {
        // 1. 校验
        if (houseNum >= houses.length) {
          System.out.println("数组已满,无法添加!");
          return false;
        }
    
        // 2. 实现添加房屋并更新 id
        house.setId(houseNum + 1);
        houses[houseNum++] = house;
        return true;
      }
    }

删除房屋

image-20260206121813995

  1. HouseView.java

    java
    public class HouseView {
      /** 删除房屋 */
      private void delHouse() {
        System.out.println("-------------------- 删除房屋 --------------------");
    
        // 1. 输入-1:取消删除
        System.out.print("请选择待删除房屋编号(-1:退出):");
        int id = Utility.readInt();
        if (id == -1) {
          System.out.println("❌ 取消删除");
          return;
        }
    
        // 2. 确认是否删除(Y/N)
        char c = Utility.readConfirmSelection();
        if (c == 'Y') {
          if (houseService.del(id)) {
            System.out.println("✅ 删除成功");
          } else {
            System.out.println("❌ 删除失败,编号不存在!");
          }
        } else {
          System.out.println("❌ 取消删除");
        }
      }
    }
  2. HouseService.java

    java
    public class HouseService {
      /** 删除房屋 */
      public boolean del(int id) {
        // 1. 遍历查找要删除的房屋的下标
        int index = -1;
        for (int i = 0; i < houseNum; i++) {
          if (houses[i].getId() == id) {
            index = i;
            break;
          }
        }
    
        // 2. 没有找到
        if (index == -1) return false;
    
        // 3. ✅ 难点:找到了,执行删除逻辑(数组移位)
        for (int i = index; i < houseNum - 1; i++) {
          houses[i] = houses[i + 1];
        }
        houses[--houseNum] = null; // 最后一个元素置空
        return true;
      }
    }

作业:添加数组扩容机制【

作业:查找房屋

根据 ID 查找房屋并显示信息。

image-20260206121726721

image-20260206121741089

  1. HouseView.java

    image-20260206173505045

  2. HouseService.java

    image-20260206173339051

作业:修改房屋

根据 ID 修改房屋的姓名、电话、地址、月租、状态。

image-20260206121842312

  1. HouseView.java

    image-20260206175252741

  2. HouseService.java:(无需修改)

实现 HouseService

java
public class HouseService {
  private House[] houses; // House 对象数组

  public HouseService (int size) {
    // 1. 创建 House 对象,并指定数组大小
    houses = new House[size];

    // 2. 初始化一条数据
    houses[0] = new House(1, "jack", "112", "上海", "3000", "未出租");
  }

  // 3. 返回房屋列表
  public House[] list() {}

  // 4. 添加房屋
  public boolean add() {}

  // 5. 删除房屋
  public boolean del() {}

  // ...
}

实现 House【

封装房屋信息:

java
public class House {
  private int id; // 编号(自增长)
  private String name; // 房主
  private String phone; // 电话
  private String address; // 地址
  private double rent; // 月租
  private String status; // 状态(未出租/已出租)

  // TODO:构造器、getter/setter、toString()
}